#include "GLWidget.h"
#include <QWheelEvent>
#include <QKeyEvent>
#include <iostream>
using namespace std;

GLWidget::GLWidget(QWidget *parent) :
    QGLWidget(parent)
{
    this->zoom = 1.0;
    this->r = 0.0;
    this->g = 0.0;
    this->b = 0.0;
    rotateX(0.0);
    rotateY(0.0);
    rotateZ(0.0);
}

void GLWidget::initializeGL()
{
    //Define a cor que será usada para limpar o framebuffer
    glClearColor(0.1, 0.1, 0.12, 1.0);

    //Habilita o teste de profundidade para remoção de faces ocultas
    glEnable(GL_DEPTH_TEST);
    //Habilita cull face para não desenhar faces que estão "de costas para a câmera"
    glEnable(GL_CULL_FACE);

    //Habilita a iluminação
//    glEnable(GL_LIGHTING);
    //Habilita a fonte de luz 0 do openGL
    glEnable(GL_LIGHT0);

    //Habilita o recurso color material do openGL. Isso permite definir a cor de material apenas usando glColor...
    glEnable(GL_COLOR_MATERIAL);
    //Define o color material como amgiente e difuso. Ou seja, ao chamar glColor, o openGL vai setar a cor ambiente e difusa do material.
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

    //Define propriedades especulares de material.
    float specular[4] = {1.0, 1.0, 1.0, 1.0};   //Cor especular
    glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
    glMateriali(GL_FRONT, GL_SHININESS, 12);    //Shininess ou rugosidade do material
}

void GLWidget::paintGL()
{
    //Limpa o frame buffer de cor e de teste de profundidade
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //Muda a matriz corrente para a modelview. Essa matriz é a responsável pelas transformações de cena.
    glMatrixMode(GL_MODELVIEW);
    //Carrega a matriz identidade. Isso tem o efeito de limpar a matriz corrente, nesse caso a modelview.
    glLoadIdentity();
    //Aplica uma rotação em cada eixo
    glRotatef(rot[0], 1.0, 0.0, 0.0);
    glRotatef(rot[1], 0.0, 1.0, 0.0);
    glRotatef(rot[2], 0.0, 0.0, 1.0);
    glColor3f(r, g, b);
    //Desenha os objetos da lista
    for(int i=0; i < objects.size(); ++i)
        objects[i]->draw();
}

void GLWidget::resizeGL(int w, int h)
{
    //Calcular o aspect ratio.
    float aspect = w/(float)h;

    //Define o novo tamanho da viewport de acordo com o novo tamanho (w, h) da janela alterado pelo usuário
    glViewport(0, 0, w, h);

    //Muda a matriz corrente para projection. Essa matriz é responsável pela parte de projeção
    glMatrixMode(GL_PROJECTION);
    //Limpa a matriz corrente
    glLoadIdentity();

    //Altera o tamanho do volume de visualização para manter o aspect ratio igual ao do novo tamanho da janela.
    if(w >= h)
        glOrtho(-aspect*zoom, aspect*zoom, -zoom, zoom, -100.0, 100.0);
    else
        glOrtho(-zoom, zoom, -zoom/aspect, zoom/aspect, -100.0, 100.0);

    //Volta a matriz corrente para a modelview
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void GLWidget::wheelEvent(QWheelEvent *event)
{
    float ds = event->delta()*0.0001;

    zoom -= ds;
    zoom = zoom < 0.0 ? 0.0 : zoom;

    resizeGL(width(), height());
    updateGL();
    // Ver o valor do zoom a medida que ele é alterado:
    cout<<"GLWidget.zoom: "<<this->getZoom()<<endl;
}

void GLWidget::setRedColor(int vermelho)
{
    this->r = vermelho/255.0;
    cout<<"GLWidget.vermelho: "<<this->r<<endl;
    updateGL();
}

void GLWidget::setGreenColor(int verde)
{
    this->g = verde/255.0;
    cout<<"GLWidget.verde: "<<this->g<<endl;
    updateGL();
}

void GLWidget::setBlueColor(int azul)
{
    this->b = azul/255.0;
    cout<<"GLWidget.azul: "<<this->b<<endl;
    updateGL();
}
